home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / mush6.0 / part04 < prev    next >
Encoding:
Internet Message Format  |  1988-04-12  |  55.8 KB

  1. Subject:  v14i036:  Mail User's Shell, version 6.0, Part04/14
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: island!argv@sun.com (Dan Heller)
  7. Posting-number: Volume 14, Issue 36
  8. Archive-name: mush6.0/part04
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 4 (of 14)."
  19. # Contents:  help.c init.c misc.c pick.c setopts.c
  20. # Wrapped by rsalz@fig.bbn.com on Wed Apr 13 20:04:44 1988
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'help.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'help.c'\"
  24. else
  25. echo shar: Extracting \"'help.c'\" \(9753 characters\)
  26. sed "s/^X//" >'help.c' <<'END_OF_FILE'
  27. X/* @(#)help.c    (c) copyright 10/15/86 (Dan Heller) */
  28. X
  29. X/*
  30. X * This file conatins two main routines:
  31. X *    display_help() and find_help()
  32. X * Both are virtually equivalent in functionality; they are passed
  33. X * a char * or a char **. If a char * is passed, then open "file"
  34. X * argument (containing help strings) and search for %str% and read
  35. X * the following text until %% or EOF into a local buffer.
  36. X * If str is a char **, then that array of strings is used directly.
  37. X *
  38. X * If display_help is used, then the final array of strings used is
  39. X * displayed in the center of the bitmapped console in a box with
  40. X * shading and the user must hit the left mouse button to remove the
  41. X * message.  the fd passed is the fd of the window locking the screen.
  42. X *
  43. X * In text mode, the routine find_help is used (or, if the graphics
  44. X * mode doesn't want to lock the screen to display a message). The
  45. X * same actions occur, but instead of "ifdef"ing up one function, I
  46. X * just made two for readability.
  47. X */
  48. X#include <stdio.h>
  49. X#include "strings.h"
  50. X
  51. X#define NULL_FILE (FILE *)0
  52. X
  53. X#ifdef SUNTOOL
  54. X#include <suntool/tool_hs.h>
  55. X#include <signal.h>
  56. X#include <suntool/fullscreen.h>
  57. X
  58. X#define l_width()      font->pf_defaultsize.x /* width of letter */
  59. X#define l_height()      font->pf_defaultsize.y /* height of letter */
  60. X
  61. X#define draw(win,x1,y1,x2,y2,OP)     pw_vector(win, x1,y1,x2,y2,OP,1)
  62. X#define box(win, x1,y1,x2,y2,OP) \
  63. X    draw(win,x1,y1, x1,y2, OP), \
  64. X    draw(win,x1,y2, x2,y2, OP), \
  65. X    draw(win,x2,y2, x2,y1, OP), \
  66. X    draw(win,x2,y1, x1,y1, OP)
  67. X
  68. X#define DEF_CONT_MSG    "Click LEFT mouse Button to continue."
  69. DEFINE_CURSOR(oldcursor, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  70. X
  71. X/* shading */
  72. static short dat_shade_25[] = {
  73. X#include <images/square_25.pr>
  74. X};
  75. X
  76. static short dat_shade_50[] = {
  77. X#include <images/square_50.pr>
  78. X};
  79. X
  80. static short dat_shade_75[] = {
  81. X#include <images/square_75.pr>
  82. X};
  83. X
  84. static short dat_mouse_left[] = {
  85. X#include <images/confirm_left.pr> 
  86. X};
  87. X
  88. mpr_static(shade_25,        16, 16, 1, dat_shade_25);
  89. mpr_static(shade_50,        16, 16, 1, dat_shade_50);
  90. mpr_static(shade_75,        16, 16, 1, dat_shade_75);
  91. mpr_static(confirm_pr,      16, 16, 1, dat_mouse_left);
  92. X
  93. static struct cursor confirm_cursor = { 3, 3, PIX_SRC, &confirm_pr };
  94. static struct pixrect *shading;
  95. X
  96. X#else
  97. X
  98. X#include <sys/types.h>
  99. X#define wprint printf
  100. X#define print  printf
  101. X
  102. X#endif /* SUNTOOL */
  103. X
  104. X/* what to print if nothing was found */
  105. static char *def_msg[] = {
  106. X    "There is no help found for this item.",
  107. X    "Perhaps getting help from another item",
  108. X    "would be of some use.", 0
  109. X};
  110. X
  111. X#define MAXLINES    40
  112. X#define MAXLENGTH    128
  113. static FILE *help_file;
  114. static char file_name[128];
  115. X
  116. X#ifdef SUNTOOL
  117. display_help(fd, str, file, font)
  118. register caddr_t *str;   /* could be a single or double pointer */
  119. register char *file;
  120. register struct pixfont *font;
  121. X{
  122. X    struct fullscreen *fs;
  123. X    struct inputmask im, old_im;
  124. X    struct inputevent event;
  125. X    struct rect rect;
  126. X    register char *p;
  127. X    register int x, y, z, height;
  128. X    struct pixrect *saved, *save_bits();
  129. X    int width = 0, old_link;
  130. X    char *cont_msg = DEF_CONT_MSG, *getenv();
  131. X    char args[MAXLINES][MAXLENGTH], help_str[40];
  132. X
  133. X    if (!shading)
  134. X    if (p = getenv("SHADE")) {
  135. X        register int x = atoi(p);
  136. X        if (x <= 25)
  137. X        shading = &shade_25;
  138. X        else if (x <= 50)
  139. X        shading = &shade_50;
  140. X        else
  141. X        shading = &shade_75;
  142. X    } else
  143. X        shading = &shade_25;
  144. X
  145. X    /* If no file given, take "str" arg as message to print */
  146. X    if (!file || !*file) {
  147. X    file = NULL;
  148. X    for(height = 0; *str && height < MAXLINES-1; height++) {
  149. X        if (!compose_str(*str, &width))
  150. X        break;
  151. X        (void) strcpy(args[height], *str++);
  152. X    }
  153. X    } else {
  154. X    if (!*file_name || strcmp(file_name, file)) {
  155. X        (void) strcpy(file_name, file);
  156. X        if (help_file)
  157. X        fclose(help_file), help_file = NULL_FILE;
  158. X    }
  159. X    /* file remains open */
  160. X    if (!help_file && !(help_file = fopen(file_name, "r")))
  161. X        return -1;
  162. X    /* look for %str% in helpfile */
  163. X    (void) sprintf(help_str, "%%%s%%\n", str);
  164. X
  165. X    rewind(help_file);
  166. X
  167. X    while(p = fgets(args[0], MAXLENGTH, help_file))
  168. X        if (*p == '%' && !strcmp(p, help_str))
  169. X        break;
  170. X
  171. X    if (!p || !fgets(args[0], MAXLENGTH, help_file))
  172. X        for(height = 0; def_msg[height] && height < MAXLINES-1; height++) {
  173. X        compose_str(def_msg[height], &width);
  174. X        (void) strcpy(args[height], def_msg[height]);
  175. X        }
  176. X    else for (height = 0; p && *p && strcmp(p, "%%\n"); height++) {
  177. X        compose_str(p, &width);
  178. X        p = fgets(args[height+1], MAXLENGTH, help_file);
  179. X        }
  180. X    }
  181. X    if (height == MAXLINES - 1)
  182. X    print("Help message is too long!\n");
  183. X
  184. X    fs = fullscreen_init(fd);
  185. X    /* Figure out the height and width in pixels (rect.r_height, rect.r_width)
  186. X     * Remember to provide for the "confirm" line (cont_msg).
  187. X     * extend the new box by 15 pixels on the sides (30 total), top, and bottom.
  188. X     * finally, add 16 pixels for "shadow" -- remove before clearing area
  189. X     * to preserve background and give a shadow-like appearance.
  190. X     */
  191. X    if ((x = strlen(cont_msg)) > width)
  192. X    width = x; /* this x value must be saved! */
  193. X    rect.r_width = (width*l_width()) + 30 + 16;
  194. X    rect.r_height = ((height+1) * l_height()) + 30 + 16;
  195. X    rect.r_left = fs->fs_screenrect.r_left +
  196. X    (fs->fs_screenrect.r_width / 2) - (rect.r_width / 2);
  197. X    rect.r_top = fs->fs_screenrect.r_top +
  198. X    (fs->fs_screenrect.r_height / 2) - (rect.r_height / 2);
  199. X
  200. X    /* save old area */
  201. X    saved = save_bits(fs->fs_pixwin, &rect);
  202. X
  203. X    /* prepare surface, clear the background, and reset rect for shadow */
  204. X    pw_preparesurface(fs->fs_pixwin, &rect);
  205. X    pw_lock(fs->fs_pixwin, &rect);
  206. X    rect.r_width -= 16;
  207. X    rect.r_height -= 16;
  208. X
  209. X    pw_writebackground(fs->fs_pixwin,
  210. X    rect.r_left, rect.r_top, rect.r_width, rect.r_height, PIX_CLR);
  211. X
  212. X    /* make a box that's 5 pixels thick. Then add a thin box inside it */
  213. X    for (z = 0; z < 5; z++)
  214. X    box(fs->fs_pixwin,
  215. X        rect.r_left+z, rect.r_top+z,
  216. X        rect.r_left+rect.r_width-z-1, rect.r_top+rect.r_height-z-1,
  217. X        PIX_SRC);
  218. X    box(fs->fs_pixwin,
  219. X    rect.r_left+z+2, rect.r_top+z+2,
  220. X    rect.r_left+rect.r_width-z-3, rect.r_top+rect.r_height-z-3,
  221. X    PIX_SRC);
  222. X
  223. X    /* shading -- pw_replrop() doesn't work (bug)
  224. X     * NOTE: fs->fs_screenrect.r_top and r_left are negative values
  225. X     */
  226. X    pr_replrop(fs->fs_pixwin->pw_pixrect,
  227. X       rect.r_left + rect.r_width - fs->fs_screenrect.r_left,
  228. X       rect.r_top + 16 - fs->fs_screenrect.r_top,
  229. X       16, rect.r_height-16, PIX_SRC|PIX_DST, shading, 0, 0);
  230. X    pr_replrop(fs->fs_pixwin->pw_pixrect,
  231. X       rect.r_left + 16 - fs->fs_screenrect.r_left,
  232. X       rect.r_top+rect.r_height - fs->fs_screenrect.r_top,
  233. X       rect.r_width, 16, PIX_SRC|PIX_DST, shading, 0, 0);
  234. X
  235. X    if (x > width)
  236. X    x = 15;
  237. X    else
  238. X    x = rect.r_width/2 - (x*l_width())/2;
  239. X    y = rect.r_height - 15;
  240. X
  241. X    /* Print everything in reverse order now; start with the "confirm" string
  242. X     * (which is centered and highlighted)
  243. X     */
  244. X    pw_text(fs->fs_pixwin, rect.r_left+x, rect.r_top+y, PIX_SRC,font, cont_msg);
  245. X    pw_text(fs->fs_pixwin, rect.r_left+x+1, rect.r_top+y, PIX_SRC|PIX_DST, font,
  246. X        cont_msg);
  247. X
  248. X    y -= (5 + l_height());
  249. X    x = 15;
  250. X
  251. X    /* now print each string in reverse order (start at bottom of box) */
  252. X    for (height--; height >= 0; height--) {
  253. X    pw_text(fs->fs_pixwin, rect.r_left+x, rect.r_top+y,
  254. X        PIX_SRC, font, args[height]);
  255. X    y -= l_height();
  256. X    }
  257. X
  258. X    pw_unlock(fs->fs_pixwin);
  259. X
  260. X    /* wait for user to read and confirm */
  261. X    win_getinputmask(fd, &old_im, &old_link);
  262. X    input_imnull(&im);
  263. X    im.im_flags |= IM_ASCII;
  264. X    win_setinputcodebit(&im, MS_LEFT);
  265. X    win_setinputcodebit(&im, MS_MIDDLE);
  266. X    win_setinputcodebit(&im, MS_RIGHT);
  267. X    win_setinputmask(fd, &im, &im, WIN_NULLLINK);
  268. X    win_getcursor(fd, &oldcursor);
  269. X    win_setcursor(fd, &confirm_cursor);
  270. X    while (input_readevent(fd, &event) != -1 && event.ie_code != MS_LEFT);
  271. X
  272. X    /* restore old cursor */
  273. X    win_setcursor(fd, &oldcursor);
  274. X
  275. X    /* restore old pixrect (size already restored) */
  276. X    rect.r_height += 16; /* to take care of the shadow */
  277. X    rect.r_width += 16;
  278. X    restore_bits(fs->fs_pixwin, &rect, saved);
  279. X    /* release screen */
  280. X    fullscreen_destroy(fs);
  281. X    win_setinputmask(fd, &old_im, &old_im, old_link);
  282. X    return 0;
  283. X}
  284. X
  285. static
  286. compose_str(p, width)
  287. register char *p;
  288. int *width;
  289. X{
  290. X    register int x;
  291. X    if (!p || !*p)
  292. X    return 0;
  293. X    x = strlen(p);
  294. X    if (p[x-1] == '\n')
  295. X    p[--x] = 0; /* get rid of newline */
  296. X    if (x > *width)
  297. X    *width = x;
  298. X    return 1;
  299. X}
  300. X#endif /* SUNTOOL */
  301. X
  302. find_help(str, file)
  303. register caddr_t *str;
  304. register char *file;
  305. X{
  306. X    register char    *p;
  307. X    char        args[MAXLINES][MAXLENGTH], help_str[40];
  308. X    register int    n, height;
  309. X    extern char        *no_newln();
  310. X
  311. X    /* If no file given, take "str" arg as message to print */
  312. X    if (!file || !*file) {
  313. X    file = NULL;
  314. X    for(height = 0; *str && height < MAXLINES-1; height++)
  315. X        (void) strcpy(args[height], *str++);
  316. X    } else {
  317. X    if (!*file_name || strcmp(file_name, file)) {
  318. X        (void) strcpy(file_name, file);
  319. X        if (help_file)
  320. X        fclose(help_file), help_file = NULL_FILE;
  321. X    }
  322. X    /* file remains open */
  323. X    if (!help_file && !(help_file = fopen(file_name, "r")))
  324. X        return -1;
  325. X    /* look for %str% in helpfile */
  326. X    (void) sprintf(help_str, "%%%s%%\n", str);
  327. X    rewind(help_file);
  328. X    while(p = fgets(args[0], MAXLENGTH, help_file))
  329. X        if (*p == '%' && !strcmp(p, help_str))
  330. X        break;
  331. X    if (!p || !fgets(args[0], MAXLENGTH, help_file))
  332. X        for(height = 0; def_msg[height] && height < MAXLINES-1; height++)
  333. X        (void) strcpy(args[height], def_msg[height]);
  334. X    else for (height = 0; p && *p && strcmp(p, "%%\n"); height++)
  335. X        p = fgets(args[height+1], MAXLENGTH, help_file);
  336. X    }
  337. X    if (height == MAXLINES - 1)
  338. X    print("Help message is too long!\n");
  339. X
  340. X    for (n = 0; n < height; n++) {
  341. X    (void) no_newln(args[n]);
  342. X    wprint("%s\n", args[n]);
  343. X    }
  344. X
  345. X    return 0;
  346. X}
  347. END_OF_FILE
  348. if test 9753 -ne `wc -c <'help.c'`; then
  349.     echo shar: \"'help.c'\" unpacked with wrong size!
  350. fi
  351. # end of 'help.c'
  352. fi
  353. if test -f 'init.c' -a "${1}" != "-c" ; then 
  354.   echo shar: Will not clobber existing file \"'init.c'\"
  355. else
  356. echo shar: Extracting \"'init.c'\" \(10032 characters\)
  357. sed "s/^X//" >'init.c' <<'END_OF_FILE'
  358. X/* init.c    (c) copyright 1986 (Dan Heller) */
  359. X
  360. X/* init.c -- functions and whatnot that initialize everything */
  361. X#include "mush.h"
  362. X#include <pwd.h>
  363. X
  364. X#ifdef SUNTOOL
  365. X/* mouse symbols */
  366. short dat_mouse_left[] = {
  367. X#include <images/confirm_left.pr> 
  368. X};
  369. X
  370. short dat_mouse_middle[] = {
  371. X#include <images/confirm_middle.pr> 
  372. X};
  373. X
  374. short dat_mouse_right[] = {
  375. X#include <images/confirm_right.pr> 
  376. X};
  377. X
  378. short dat_mail_icon_1[] = {
  379. X#include "mail.icon.1"
  380. X};
  381. X
  382. short dat_mail_icon_2[] = {
  383. X#include "mail.icon.2"
  384. X};
  385. X
  386. short dat_coffee_cup[] = {
  387. X#include "coffee.cup.pr"
  388. X};
  389. X
  390. short dat_read_cursor[] = {
  391. X#include "glasses.pr"
  392. X};
  393. X
  394. short dat_write_cursor[] = {
  395. X#include "write.pr"
  396. X};
  397. X
  398. short dat_up_arrow[] = {
  399. X#include "up.arrow.pr"
  400. X};
  401. X
  402. short dat_dn_arrow[] = {
  403. X#include "dn.arrow.pr"
  404. X};
  405. X
  406. short dat_envelope[] = {
  407. X#include "envelope.pr"
  408. X};
  409. X
  410. short dat_cycle_cursor[] = {
  411. X#include "cycle.pr"
  412. X};
  413. X
  414. short dat_check_cursor[] = {
  415. X#include "check.pr"
  416. X};
  417. X
  418. mpr_static(mail_icon_image1, 64, 64, 1, dat_mail_icon_1);
  419. mpr_static(mail_icon_image2, 64, 64, 1, dat_mail_icon_2);
  420. X
  421. mpr_static(mouse_left,      16, 16, 1, dat_mouse_left);
  422. mpr_static(mouse_middle,    16, 16, 1, dat_mouse_middle);
  423. mpr_static(mouse_right,     16, 16, 1, dat_mouse_right);
  424. mpr_static(coffee_cup,      16, 16, 1, dat_coffee_cup);
  425. mpr_static(glasses_cursor,  16, 16, 1, dat_read_cursor);
  426. mpr_static(pencil_cursor,   16, 16, 1, dat_write_cursor);
  427. mpr_static(up_arrow,        16, 16, 1, dat_up_arrow);
  428. mpr_static(dn_arrow,        16, 16, 1, dat_dn_arrow);
  429. mpr_static(envelope_cursor, 16, 16, 1, dat_envelope);
  430. mpr_static(cycle,           16, 16, 1, dat_cycle_cursor);
  431. mpr_static(check_cursor,    16, 16, 1, dat_check_cursor);
  432. X
  433. struct cursor l_cursor     = { 3, 3, PIX_SRC,         &mouse_left      };
  434. struct cursor m_cursor     = { 3, 3, PIX_SRC,         &mouse_middle    };
  435. struct cursor r_cursor     = { 3, 3, PIX_SRC,         &mouse_right     };
  436. struct cursor coffee       = { 8, 8, PIX_SRC,         &coffee_cup      };
  437. struct cursor read_cursor  = { 8, 8, PIX_SRC|PIX_DST, &glasses_cursor  };
  438. struct cursor write_cursor = { 8, 8, PIX_SRC|PIX_DST, &pencil_cursor   };
  439. struct cursor main_cursor  = { 8, 8, PIX_SRC,         &envelope_cursor };
  440. struct cursor checkmark = { 8, 8, PIX_SRC|PIX_DST, &check_cursor };
  441. X
  442. X/* text and font will be set in mail_status() */
  443. struct icon mail_icon = { 64,  64, (struct pixrect *)NULL,
  444. X            { 0, 0, 64, 64 }, &mail_icon_image1,
  445. X            { 5, 5, 26, 12 }, NULL, (struct pixfont *)NULL, 0 };
  446. X
  447. char *font_files[] = {
  448. X    "serif.r.14", "sail.r.6", "serif.r.16",
  449. X};
  450. X
  451. char *alt_fonts[] = {
  452. X    "gacha.r.8", "sail.r.6", "screen.r.14",
  453. X};
  454. X
  455. X#endif /* SUNTOOL */
  456. X
  457. X#ifdef BSD
  458. X#include <netdb.h>
  459. X#endif /* BSD */
  460. X
  461. void
  462. init()
  463. X{
  464. X    char         *home;
  465. X    extern char        *getlogin();
  466. X#ifdef SYSV
  467. X    extern struct passwd *getpwuid();  /* sys-v forgot this in pwd.h! */
  468. X#else
  469. X    char ourhost[128];
  470. X#endif /* SYSV */
  471. X    register char     *p;
  472. X    struct passwd     *entry;
  473. X    int            cnt = 0;
  474. X#ifdef BSD
  475. X    struct hostent     *hp;
  476. X#endif /* BSD */
  477. X
  478. X    home = getenv ("HOME");
  479. X
  480. X    if (!(entry = getpwuid(getuid())))
  481. X    if (p = getlogin())
  482. X        strdup(login, p);
  483. X    else {
  484. X        login = "unknown";
  485. X        print("I don't know you, but that's ok.\n");
  486. X    }
  487. X    else {
  488. X    strdup(login, entry->pw_name);
  489. X    if (!home || !*home)
  490. X        home = entry->pw_dir;
  491. X    endpwent();
  492. X    }
  493. X    if (!home || !*home || Access(home, W_OK)) {
  494. X    if (home && *home)
  495. X        error(home);
  496. X    else
  497. X        print("No home!? ");
  498. X    print_more("Using \"%s\" as home.\n", ALTERNATE_HOME);
  499. X    } else {
  500. X    char buf[MAXPATHLEN];
  501. X    cmd_line(sprintf(buf, "set home=\"%s\"", home), msg_list);
  502. X    }
  503. X    crt = 25;
  504. X    screen = 18;
  505. X    escape = DEF_ESCAPE;
  506. X    prompt = DEF_PROMPT;
  507. X
  508. X#ifndef SYSV
  509. X    (void) gethostname(ourhost, sizeof ourhost);
  510. X    if (!(hp = gethostbyname(ourhost)))
  511. X    error("gethostbyname: %s", ourhost);
  512. X    else for (p = hp->h_name; p && *p && cnt < MAX_HOST_NAMES;
  513. X          p = hp->h_aliases[cnt++])
  514. X    ourname[cnt] = savestr(p);
  515. X    endhostent();
  516. X#endif /* SYSV */
  517. X
  518. X#ifdef CURSES
  519. X    init_bindings();
  520. X#endif /* CURSES */
  521. X}
  522. X
  523. X/*
  524. X * Source a file, or just the default file.  Since sourcing files
  525. X * means reading possible aliases, don't expand the ! as history
  526. X * by setting the IGN_BANG flag.  Since a command in the sourced file
  527. X * may call source on another file, this routine may be called from
  528. X * within itself.  Continue to ignore ! chars by setting save_bang (local).
  529. X *
  530. X * Try opening the file passed to us.  If not given, check for the correct
  531. X * .rc file which is found in the user's home dir.
  532. X */
  533. source(argc, argv)
  534. char **argv;
  535. X{
  536. X    register char *p, *p2, **newargv;
  537. X    int       line_no = 0, if_else = 0, parsing = 1, cont_line = 0;
  538. X    FILE      *fp;
  539. X    char       file[128], line[BUFSIZ];
  540. X    u_long      save_bang = ison(glob_flags, IGN_BANG);
  541. X
  542. X    if (argc && *++argv && !strcmp(*argv, "-?"))
  543. X    return help(0, "source_help", cmd_help);
  544. X    if (argc && *argv)
  545. X    (void) strcpy(file, *argv);
  546. X    else if (p = getenv("MAILRC"))
  547. X    (void) strcpy(file, p);
  548. X    else {
  549. X    char *home = do_set(set_options, "home");
  550. X    if (!home || !*home)
  551. X        home = ALTERNATE_HOME;
  552. X    if (Access(sprintf(file, "%s/%s", home, MAILRC), R_OK)
  553. X          && Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), R_OK))
  554. X    (void) strcpy(file, DEFAULT_RC);
  555. X    }
  556. X
  557. X    argc = 0; /* don't ignore ENOENT */
  558. X    p = getpath(file, &argc);
  559. X    if (argc) {
  560. X    if (strcmp(file, DEFAULT_RC))
  561. X        if (argc == -1)
  562. X        print("%s: %s\n", file, p);
  563. X        else
  564. X        print("%s is a directory.\n", file);
  565. X    return -1;
  566. X    }
  567. X    if (!(fp = fopen(p, "r"))) {
  568. X    if (errno != ENOENT)
  569. X        error("Can't open %s", p);
  570. X    return -1;
  571. X    }
  572. X    (void) strcpy(file, p);
  573. X    turnon(glob_flags, IGN_BANG); /* ignore ! when reading record files */
  574. X    while (p = fgets(&line[cont_line], BUFSIZ - cont_line, fp)) {
  575. X    line_no++;
  576. X    if (*(p2 = no_newln(p)) == '\\') {
  577. X        cont_line = p2 - line;
  578. X        continue;
  579. X    } else
  580. X        cont_line = 0;
  581. X    /* don't consider comments (#) in lines. check if # is within quotes */
  582. X        if (p = any(line, "\"'#")) {
  583. X        register int balanced = 1;
  584. X        while (p && (*p == '\'' || *p == '"') && balanced) {
  585. X        /* first find matching quote */
  586. X        register char *quote = index(p+1, *p);
  587. X        if (!quote) {
  588. X            print("%s: line %d: unbalanced %c.\n", file, line_no, *p);
  589. X            balanced = 0;
  590. X        } else
  591. X            p = any(quote+1, "'\"#");
  592. X        }
  593. X        if (!balanced)
  594. X        continue;
  595. X        if (p && *p == '#')
  596. X        *p = 0; /* found a Comment: null terminate line at comment */
  597. X    }
  598. X    if (!*line || !(newargv = make_command(line, TRPL_NULL, &argc))) {
  599. X        if (!strncmp(line, "if", 2))
  600. X        if_else++, parsing = FALSE;
  601. X        continue;
  602. X    }
  603. X    if (!strcmp(newargv[0], "endif")) {
  604. X        if (!if_else)
  605. X        print("%s: line %d: endif with no \"if\".\n", file, line_no);
  606. X        else
  607. X        if_else = 0, parsing = 1;
  608. X        goto bad;
  609. X    } else if (!strcmp(newargv[0], "else")) {
  610. X        if (!if_else)
  611. X        print("%s: line %d: if-less \"else\".\n", file, line_no);
  612. X        else
  613. X        parsing = !parsing;
  614. X        goto bad;
  615. X    } else if (parsing && !strcmp(newargv[0], "if")) {
  616. X        /* if statements are of the form:
  617. X         *     if expr
  618. X         *     if !expr  or  if ! expr
  619. X         *     if expr == expr   or   if expr != expr
  620. X         */
  621. X        int equals = TRUE;
  622. X        register char *lhs = newargv[1], *rhs = NULL;
  623. X
  624. X        if (if_else)
  625. X        print("%s: line %d: no nested if statements!\n", file, line_no);
  626. X        else
  627. X        if_else = 1;
  628. X        parsing = 0;
  629. X        if (!lhs || !*lhs) {
  630. X        print("%s: line %d: if what?\n", file, line_no);
  631. X        goto bad;
  632. X        }
  633. X        /* "lhs" is the left hand side of the equation
  634. X         * In this instance, we're doing case 2 above.
  635. X         */
  636. X        if (*lhs == '!') {
  637. X        int tmp = argc;
  638. X        equals = FALSE;
  639. X        if (!*++lhs)
  640. X            if (!(lhs = newargv[2])) {
  641. X            print("%s: %d: syntax error: \"if ! <what?>\"\n",
  642. X                file, line_no);
  643. X            goto bad;
  644. X            } else
  645. X            tmp--;
  646. X        if (tmp > 2) {
  647. X            print("%s: %d: syntax error: \"if !<expr> <more junk>\"\n",
  648. X            file, line_no);
  649. X            goto bad;
  650. X        }
  651. X        } else if (argc > 2) {
  652. X        if (argc != 4) {
  653. X            print("%s: %d: argument count error: line has %d args.\n",
  654. X            file, line_no, argc);
  655. X            goto bad;
  656. X        }
  657. X        /* now check newargv[1] for == or != */
  658. X        if (!strcmp(newargv[2], "!="))
  659. X            equals = FALSE;
  660. X        else if (strcmp(newargv[2], "==")) {
  661. X            print("%s: %d: use `==' or `!=' only.\n", file, line_no);
  662. X            goto bad;
  663. X        }
  664. X        rhs = newargv[3];
  665. X        }
  666. X        if (!strcmp(lhs, "redirect") &&
  667. X              (ison(glob_flags, REDIRECT) && equals ||
  668. X               isoff(glob_flags, REDIRECT) && !equals)
  669. X        || !strcmp(lhs, "is_sending") &&
  670. X              (ison(glob_flags, IS_SENDING) && equals ||
  671. X               isoff(glob_flags, IS_SENDING) && !equals)
  672. X        || !strcmp(lhs, "hdrs_only") &&
  673. X              (hdrs_only && equals || !hdrs_only && !equals)
  674. X        || !strcmp(lhs, "istool") &&
  675. X              (istool && equals || !istool && !equals)
  676. X        || !strcmp(lhs, "iscurses") &&
  677. X              ((iscurses || ison(glob_flags, PRE_CURSES)) && equals ||
  678. X              (isoff(glob_flags, PRE_CURSES) && !iscurses && !equals)))
  679. X            parsing = 1;
  680. X        else if (rhs)
  681. X        if (strcmp(lhs, rhs) && !equals || !strcmp(lhs, rhs) && equals)
  682. X            parsing = 1;
  683. bad:
  684. X        free_vec(newargv);
  685. X        continue;
  686. X    }
  687. X    if (parsing && argc > 0)
  688. X        if (!strcmp(newargv[0], "exit")) {
  689. X        if_else = 0;
  690. X        break;
  691. X        } else
  692. X        (void) do_command(argc, newargv, msg_list);
  693. X    else
  694. X        free_vec(newargv);
  695. X    }
  696. X    if (if_else)
  697. X    print("%s: missing endif\n", file);
  698. X    fclose(fp);
  699. X    /* if we entered the routine ignoring !, leave it that way. */
  700. X    if (!save_bang)
  701. X    turnoff(glob_flags, IGN_BANG);
  702. X    return -1;
  703. X}
  704. X
  705. X#ifdef SUNTOOL
  706. X/* open all fonts and place in fonts array. */
  707. getfonts()
  708. X{
  709. X    char tmp[80];
  710. X    register int offset = strlen(FONTDIR) + 1;
  711. X    struct pixfont *pf_open();
  712. X
  713. X    (void) sprintf(tmp, "%s/", FONTDIR);
  714. X    for (total_fonts = 0; total_fonts < MAX_FONTS; total_fonts++) {
  715. X    (void) strcpy(&tmp[offset], font_files[total_fonts]);
  716. X    if (!(fonts[total_fonts] = pf_open(tmp))) {
  717. X        (void) strcpy(&tmp[offset], alt_fonts[total_fonts]);
  718. X        if (!(fonts[total_fonts] = pf_open(tmp))) {
  719. X        print("couldn't open font \"%s\"\n", tmp);
  720. X        fonts[total_fonts] = pf_default();
  721. X        }
  722. X    }
  723. X    }
  724. X}
  725. X#endif /* SUNTOOL */
  726. END_OF_FILE
  727. if test 10032 -ne `wc -c <'init.c'`; then
  728.     echo shar: \"'init.c'\" unpacked with wrong size!
  729. fi
  730. # end of 'init.c'
  731. fi
  732. if test -f 'misc.c' -a "${1}" != "-c" ; then 
  733.   echo shar: Will not clobber existing file \"'misc.c'\"
  734. else
  735. echo shar: Extracting \"'misc.c'\" \(10953 characters\)
  736. sed "s/^X//" >'misc.c' <<'END_OF_FILE'
  737. X/* @(#)misc.c    (c) copyright 10/18/86 (Dan Heller) */
  738. X
  739. X#include "mush.h"
  740. X
  741. X/* check to see if a string describes a message that is within the range of
  742. X * all messages; if invalid, return 0 and print error. else return msg number
  743. X */
  744. chk_msg(s)
  745. register char *s;
  746. X{
  747. X    register int n;
  748. X
  749. X    if ((n = atoi(s)) > 0 && n <= msg_cnt)
  750. X    return n;
  751. X    else if (*s == '^' && msg_cnt)
  752. X    return 1;
  753. X    else if (*s == '$' && msg_cnt)
  754. X    return msg_cnt;
  755. X    else if (*s == '.' && msg_cnt)
  756. X    return current_msg+1;
  757. X    print("Invalid message number: %s\n", s);
  758. X    return 0;
  759. X}
  760. X
  761. X/*
  762. X * loop thru all msgs starting with current_msg and find next undeleted
  763. X * message.  If the variable "wrap" is set, wrap to the beginning of the
  764. X * message list if we hit the end.  otherwise, stop at the end of the list.
  765. X */
  766. next_msg()
  767. X{
  768. X    register int n = current_msg;
  769. X    register int wrap = !!do_set(set_options, "wrap");
  770. X
  771. X    if (!msg_cnt)
  772. X    return current_msg = 0;
  773. X    for (n++; n != current_msg; n++)
  774. X    if (n == msg_cnt)     /* hit the end, start back at the beginning */
  775. X        if (!wrap)
  776. X        return current_msg = msg_cnt - 1;
  777. X        else
  778. X        n = -1; /* increments to 0 in  loop  */
  779. X    else if (isoff(msg[n].m_flags, DELETE))
  780. X        return current_msg = n;
  781. X    return current_msg = 0;
  782. X}
  783. X
  784. X/* since print_help just prints help, always return help() */
  785. print_help(argc, argv)
  786. register char **argv;
  787. X{
  788. X#ifdef SUNTOOL
  789. X    if (istool)
  790. X    return help(tool->tl_windowfd, "general", tool_help);
  791. X#endif /* SUNTOOL */
  792. X    if (!argc || !*++argv)
  793. X    return help(0, "general", cmd_help);
  794. X    return help(0, *argv, cmd_help);
  795. X}
  796. X
  797. X/* since this function does not affect messages, return -1 */
  798. help(fd, str, file)
  799. X#ifdef SUNTOOL
  800. caddr_t *str;
  801. X#else
  802. char *str;
  803. X#endif /* SUNTOOL */
  804. char *file;
  805. X{
  806. X#ifdef SUNTOOL
  807. X    if (istool > 1) {
  808. X    int oldmask;
  809. X    if (!fd)
  810. X        fd = print_sw->ts_windowfd;
  811. X    oldmask = sigblock(1 << ((SIGALRM) - 1));
  812. X    lock_cursors();
  813. X    if (display_help(fd, str, file, fonts[LARGE]) && file)
  814. X        error("can't read %s", file);
  815. X    unlock_cursors();
  816. X    (void) sigsetmask(oldmask);
  817. X    } else
  818. X#endif /* SUNTOOL */
  819. X    if (find_help(str, file) && file)
  820. X    error("can't read %s", file);
  821. X    return -1; /* doesn't affect any messages */
  822. X}
  823. X
  824. X#ifdef SUNTOOL
  825. void
  826. unlock_cursors()
  827. X{
  828. X    if (istool < 2)
  829. X    return;
  830. X    win_setcursor(print_sw->ts_windowfd, &main_cursor);
  831. X    win_setcursor(panel_sw->ts_windowfd, &main_cursor);
  832. X    if (getting_opts)
  833. X    win_setcursor(msg_sw->ts_windowfd, &checkmark);
  834. X    else if (ison(glob_flags, IS_GETTING))
  835. X    win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  836. X    else
  837. X    win_setcursor(msg_sw->ts_windowfd, &read_cursor);
  838. X    win_setcursor(hdr_panel_sw->ts_windowfd, &main_cursor);
  839. X    win_setcursor(hdr_sw->ts_windowfd, &l_cursor);
  840. X}
  841. X
  842. void
  843. lock_cursors()
  844. X{
  845. X    if (istool < 2)
  846. X    return;
  847. X    win_setcursor(hdr_sw->ts_windowfd, &coffee);
  848. X    win_setcursor(print_sw->ts_windowfd, &coffee);
  849. X    win_setcursor(panel_sw->ts_windowfd, &coffee);
  850. X    win_setcursor(msg_sw->ts_windowfd, &coffee);
  851. X    win_setcursor(hdr_panel_sw->ts_windowfd, &coffee);
  852. X}
  853. X
  854. X#include <suntool/fullscreen.h>
  855. X/* return the event-id that confirmed */
  856. confirm(fd)
  857. X{
  858. X    struct fullscreen *fs;
  859. X
  860. X    struct inputmask im;
  861. X    struct inputevent event;
  862. X
  863. X    fs = fullscreen_init(fd);
  864. X    input_imnull(&im);
  865. X    im.im_flags |= IM_ASCII;
  866. X    win_setinputcodebit(&im, MS_LEFT);
  867. X    win_setinputcodebit(&im, MS_MIDDLE);
  868. X    win_setinputcodebit(&im, MS_RIGHT);
  869. X    win_setinputmask(fd, &im, &im, WIN_NULLLINK);
  870. X    win_setcursor(fd, &l_cursor);
  871. X    if (input_readevent(fd, &event) == -1)
  872. X    error("confim failed");
  873. X    fullscreen_destroy(fs);
  874. X    return ID;
  875. X}
  876. X#endif /* SUNTOOL */
  877. X
  878. X/* return -1 on error or number of arguments in argv that were parsed */
  879. get_msg_list(argv, list)
  880. register char **argv;
  881. char list[];
  882. X{
  883. X    register char *p2, *p;
  884. X    char buf[256];
  885. X    register int n;
  886. X
  887. X    if (!msg_cnt) {
  888. X    print("No messages.\n");
  889. X    return -1;
  890. X    }
  891. X    if (!argv || !*argv) {
  892. X    if (isoff(glob_flags, IS_PIPE))
  893. X        set_msg_bit(list, current_msg);
  894. X    return 0;
  895. X    }
  896. X    /* first, stuff argv's args into a single char array buffer */
  897. X    (void) argv_to_string(buf, argv);
  898. X    p = buf;
  899. X    Debug("get_msg_list: parsing: (%s): ", p);
  900. X    /*
  901. X     * if do_range returns NULL, an invalid message was specified
  902. X     */
  903. X    if (!(p2 = do_range(p, list)))
  904. X    return -1;
  905. X    /*
  906. X     * if p2 == p (and p isn't $ or ^ or .), then no message list was
  907. X     * specified.  set the current message in such cases if we're not piping
  908. X     */
  909. X    if (p2 == p) {
  910. X    if (*p == '$')
  911. X        set_msg_bit(list, msg_cnt-1);
  912. X    else if (*p == '^')
  913. X        set_msg_bit(list, 0);
  914. X    else if (*p == '.' || isoff(glob_flags, IS_PIPE))
  915. X        set_msg_bit(list, current_msg);
  916. X    }
  917. X    for (n = 0; p2 > p && *argv; n++)
  918. X    p2 -= (strlen(*argv++)+1);
  919. X    Debug("parsed %d args\n", n);
  920. X    return n;
  921. X}
  922. X
  923. X#ifdef NOT_NEEDED_NOW
  924. X/* return whether or not this process is in the foreground or background */
  925. foreground()
  926. X{
  927. X#ifdef TIOCGPGRP
  928. X    int tpgrp;    /* short in 4.1, int in 4.2 */
  929. X
  930. X    if (ioctl(0, TIOCGPGRP, (char *)&tpgrp))
  931. X    return 0;
  932. X    return tpgrp == getpgrp(0);
  933. X#else
  934. X    return 1;
  935. X#endif /* TIOCGPGRP */
  936. X}
  937. X#endif /* NOT_NEEDED_NOW */
  938. X
  939. X/*
  940. X * execute a command from a string.  f'rinstance: "pick -f foobar"
  941. X * The string is made into an argv and then run.  Errors are printed
  942. X * if the command failed to make.
  943. X *   NOTES:
  944. X *     NEVER pass stright text: e.g. "pick -f foobar", ALWAYS strcpy(buf, "...")
  945. X *     no history is expanded (ignore_bang).
  946. X */
  947. cmd_line(buf, list)
  948. char buf[], list[];
  949. X{
  950. X    register char **argv;
  951. X    int argc, ret_val = -1;
  952. X    u_long save_do_pipe = ison(glob_flags, DO_PIPE);
  953. X    u_long save_is_pipe = ison(glob_flags, IS_PIPE);
  954. X
  955. X    turnoff(glob_flags, DO_PIPE);
  956. X    turnoff(glob_flags, IS_PIPE);
  957. X    if (argv = make_command(buf, TRPL_NULL, &argc))
  958. X    ret_val = do_command(argc, argv, list);
  959. X    if (save_do_pipe)
  960. X    turnon(glob_flags, DO_PIPE);
  961. X    else
  962. X    turnoff(glob_flags, DO_PIPE);
  963. X    if (save_is_pipe)
  964. X    turnon(glob_flags, IS_PIPE);
  965. X    else
  966. X    turnoff(glob_flags, IS_PIPE);
  967. X    return ret_val;
  968. X}
  969. X
  970. glob_test(s)
  971. char *s;
  972. X{
  973. X    print("%s: glob_flags =", s);
  974. X    if (ison(glob_flags, DO_UPDATE))
  975. X    print_more(" DO_UPDATE");
  976. X    if (ison(glob_flags, REV_VIDEO))
  977. X    print_more(" REV_VIDEO");
  978. X    if (ison(glob_flags, CONT_PRNT  ))
  979. X    print_more(" CONT_PRNT");
  980. X    if (ison(glob_flags, DO_SHELL    ))
  981. X    print_more(" DO_SHELL");
  982. X    if (ison(glob_flags, DO_PIPE))
  983. X    print_more(" DO_PIPE");
  984. X    if (ison(glob_flags, IS_PIPE))
  985. X    print_more(" IS_PIPE");
  986. X    if (ison(glob_flags, IGN_SIGS))
  987. X    print_more(" IGN_SIGS");
  988. X    if (ison(glob_flags, IGN_BANG))
  989. X    print_more(" IGN_BANG");
  990. X    if (ison(glob_flags, ECHO_FLAG))
  991. X    print_more(" ECHO_FLAG");
  992. X    if (ison(glob_flags, IS_GETTING))
  993. X    print_more(" IS_GETTING");
  994. X    if (ison(glob_flags, PRE_CURSES))
  995. X    print_more(" PRE_CURSES");
  996. X    if (ison(glob_flags, READ_ONLY  ))
  997. X    print_more(" READ_ONLY");
  998. X    if (ison(glob_flags, REDIRECT))
  999. X    print_more(" REDIRECT");
  1000. X    if (ison(glob_flags, WAS_INTR ))
  1001. X    print_more(" WAS_INTR");
  1002. X    if (ison(glob_flags, WARNING   ))
  1003. X    print_more(" WARNING");
  1004. X    print_more("\n");
  1005. X}
  1006. X
  1007. msg_flags(c, v, list)
  1008. register char **v, *list;
  1009. X{
  1010. X    register int    i;
  1011. X    register u_long    newflag = 0;
  1012. X
  1013. X    if (c && *++v && !strcmp(*v, "-?"))
  1014. X    return help(0, "msg_flags", cmd_help);
  1015. X    if (c && (c = get_msg_list(v, list)) == -1)
  1016. X    return -1;
  1017. X    if (v && *(v += (c-1))) {
  1018. X    turnon(glob_flags, DO_UPDATE);
  1019. X    while (*++v)
  1020. X        for (c = 0; v[0][c]; c++)
  1021. X        switch (lower(v[0][c])) {
  1022. X            case 'n' : turnon(newflag, UNREAD), turnoff(newflag, OLD);
  1023. X            when 'd' : turnon(newflag, DELETE);
  1024. X            when 'p' : turnon(newflag, PRESERVE);
  1025. X            when 'u' : turnon(newflag, UNREAD); /* fall thru! */
  1026. X            case 'o' : turnon(newflag, OLD);
  1027. X            when 'r' :
  1028. X            if (v[0][c] == 'R')
  1029. X                turnoff(newflag, UNREAD), turnon(newflag, OLD);
  1030. X            else
  1031. X                turnon(newflag, REPLIED);
  1032. X            otherwise: return help(0, "msg_flags", cmd_help);
  1033. X        }
  1034. X    }
  1035. X
  1036. X    for (i = 0; i < msg_cnt; i++) {
  1037. X    if (!msg_bit(list, i))
  1038. X        continue;
  1039. X    else if (!newflag) {
  1040. X        wprint("msg %d: offset: %d, lines: %d, bytes: %d, flags:", i+1,
  1041. X        msg[i].m_offset, msg[i].m_lines, msg[i].m_size);
  1042. X        if (ison(msg[i].m_flags, UNREAD))
  1043. X        wprint(" UNREAD");
  1044. X        if (ison(msg[i].m_flags, OLD))
  1045. X        wprint(" OLD");
  1046. X        if (ison(msg[i].m_flags, DELETE))
  1047. X        wprint(" DELETE");
  1048. X        if (ison(msg[i].m_flags, PRESERVE))
  1049. X        wprint(" PRESERVE");
  1050. X        if (ison(msg[i].m_flags, REPLIED))
  1051. X        wprint(" REPLIED");
  1052. X        if (ison(msg[i].m_flags, UPDATE_STATUS))
  1053. X        wprint(" UPDATE_STATUS");
  1054. X        wprint("\n");
  1055. X    } else
  1056. X        msg[i].m_flags = newflag;
  1057. X    }
  1058. X    return 0;
  1059. X}
  1060. X
  1061. X/*
  1062. X * Internal pager.  Start the internal pager by passing the name of
  1063. X * the pager in buf and passing TRUE as start_pager. If the internal
  1064. X * pager is desired, pass NULL as buf.  Continue paging by passing
  1065. X * FALSE as start_page and the buf is the stuff to pass thru to the
  1066. X * pager.  End paging by passing NULL as buf and FALSE as start_flag.
  1067. X * If the pager can't be used, or is null, we're paging ourselves.
  1068. X * The -e command line flag (tty echoing done by terminal driver) makes
  1069. X * this internal paging ugly, but hey -- such users get what they pay for.
  1070. X * Windows does nothing but echo buf to the msg window.
  1071. X * The "buff" passed to the pager should be a line at a time so as to
  1072. X * count \n's.  It could be modified to count \n's, but that'd be slow.
  1073. X * Return EOF if pager died, user exited pager, or if user types 'q'
  1074. X * at the --more-- prompt for the internal pager.
  1075. X */
  1076. do_pager(buf, start_pager)
  1077. register char *buf;
  1078. X{
  1079. X    static FILE *pp;
  1080. X    static int cnt;
  1081. X
  1082. X#ifdef SUNTOOL
  1083. X    if (istool) {
  1084. X    if (buf && !start_pager)
  1085. X        Addstr(buf);
  1086. X    return 0;
  1087. X    }
  1088. X#endif /* SUNTOOL */
  1089. X    if (start_pager) {
  1090. X    turnon(glob_flags, IGN_SIGS);
  1091. X    if (!buf)
  1092. X        pp = stdout;
  1093. X    else if (!(pp = popen(buf, "w")))
  1094. X        error(buf);
  1095. X    else
  1096. X        echo_on();
  1097. X    cnt = 0;
  1098. X    } else if (!buf) {
  1099. X    if (pp && pp != stdout)
  1100. X        pclose(pp);
  1101. X    pp = NULL_FILE;
  1102. X    echo_off();
  1103. X    turnoff(glob_flags, IGN_SIGS);
  1104. X    } else if (pp != stdout)
  1105. X    return fputs(buf, pp); /* returns EOF if user exited pager */
  1106. X    else {
  1107. X    register char c = 0, *cr = index(buf, '\n');
  1108. X    if (cr && (c = *++cr) != '\0')
  1109. X        *cr = 0; /* send one line to stdout and prompt for more */
  1110. X    (void) fputs(buf, pp);
  1111. X    if (cr && !(++cnt % (crt-1))) {
  1112. X        int n = c_more(NULL);
  1113. X        if (n == '\n' || n == '\r')
  1114. X        cnt--; /* go line by line */
  1115. X        else if (n == CTRL(D) || n < 0) {
  1116. X        clearerr(stdin);
  1117. X        cnt += (cnt/2);
  1118. X        } else if (lower(n) == 'q')
  1119. X        return EOF;
  1120. X    }
  1121. X    if (c) {
  1122. X        *cr = c;
  1123. X        return do_pager(cr, FALSE);
  1124. X    }
  1125. X    }
  1126. X    return 0;
  1127. X}
  1128. X
  1129. X/* curses based "more" like option */
  1130. c_more(p)
  1131. register char *p;
  1132. X{
  1133. X    register int c;
  1134. X
  1135. X    if (!p)
  1136. X    p = "--more--";
  1137. X    print_more(p);
  1138. X    
  1139. X    while ((c = getchar()) >= 0 && c != CTRL(D) && !isspace(c) &&
  1140. X       c != '\n' && c != '\r' && lower(c) != 'q')
  1141. X    bell();
  1142. X    if (ison(glob_flags, ECHO_FLAG) && c != '\n' && c != '\r')
  1143. X    while (getchar() != '\n');
  1144. X    printf("\r%*c\r", strlen(p), ' '), fflush(stdout); /* remove the prompt */
  1145. X    return c;
  1146. X}
  1147. END_OF_FILE
  1148. if test 10953 -ne `wc -c <'misc.c'`; then
  1149.     echo shar: \"'misc.c'\" unpacked with wrong size!
  1150. fi
  1151. # end of 'misc.c'
  1152. fi
  1153. if test -f 'pick.c' -a "${1}" != "-c" ; then 
  1154.   echo shar: Will not clobber existing file \"'pick.c'\"
  1155. else
  1156. echo shar: Extracting \"'pick.c'\" \(10751 characters\)
  1157. sed "s/^X//" >'pick.c' <<'END_OF_FILE'
  1158. X/* @(#)pick.c    2.4    (c) copyright 10/18/86 (Dan Heller) */
  1159. X
  1160. X#include "mush.h"
  1161. X
  1162. static int before, mdy[3], search_from, search_subj, search_to, xflg, icase;
  1163. static search_hdr[64];
  1164. X
  1165. do_pick(n, argv, list)
  1166. register int n;
  1167. register char **argv, list[];
  1168. X{
  1169. X    if (n > 1 && !strcmp(argv[1], "-?"))
  1170. X    return help(0, "pick", cmd_help);
  1171. X
  1172. X    /* if is_pipe, then the messages to search for are already set.
  1173. X     * if not piped, then reverse the bits for all message numbers.
  1174. X     * That is, search EACH message. only those matching will be returned.
  1175. X     */
  1176. X    if (isoff(glob_flags, IS_PIPE))
  1177. X    bitput(list, list, msg_cnt, =~) /* macro, turn on all bits */
  1178. X    if (pick(n, argv, list, isoff(glob_flags, DO_PIPE)) == -1)
  1179. X    return -1;
  1180. X    if (isoff(glob_flags, DO_PIPE)) {
  1181. X    if (istool)
  1182. X        print("Messages: ");
  1183. X    for (n = 0; n < msg_cnt; n++)
  1184. X        if (msg_bit(list, n))
  1185. X        if (istool)
  1186. X            print_more("%d ", n+1);
  1187. X        else
  1188. X            print("%s\n", compose_hdr(n));
  1189. X    }
  1190. X    return 0;
  1191. X}
  1192. X
  1193. pick(ret, argv, list, verbose)
  1194. register int ret;
  1195. register char **argv, list[];
  1196. X{
  1197. X    register char c;
  1198. X    int o_before = before, o_mdy[3], o_search_from = search_from,
  1199. X    o_search_subj = search_subj, o_search_to = search_to, o_xflg = xflg, n;
  1200. X
  1201. X    for (c = 0; c < 3; c++)
  1202. X    o_mdy[c] = mdy[c];
  1203. X
  1204. X    ret = -1;
  1205. X    if (!msg_cnt) {
  1206. X    print("No Messages.\n");
  1207. X    goto bad;
  1208. X    }
  1209. X
  1210. X    icase = before = search_from = search_subj = xflg = 0;
  1211. X    mdy[0] = search_hdr[0] = 0;
  1212. X    while (*argv && *++argv && **argv == '-')
  1213. X    switch(c = argv[0][1]) {
  1214. X        /* users specifies a range */
  1215. X        case 'r': {
  1216. X        int X = 2;
  1217. X        /* if not a pipe, then clear all bits cuz we only want
  1218. X         * to search the message specified here...
  1219. X         * If it is a pipe, then add to the messages searched for.
  1220. X         */
  1221. X        if (isoff(glob_flags, IS_PIPE))
  1222. X            clear_msg_list(list);
  1223. X        /*  "-r10-15"
  1224. X         *     ^argv[1][2]  if NULL, then
  1225. X         * list detached from "r" e.g. "-r" "5-20"
  1226. X         */
  1227. X        if (!argv[0][X])
  1228. X            argv++, X = 0;
  1229. X        (*argv) += X;
  1230. X        n = get_msg_list(argv, list);
  1231. X        (*argv) -= X;
  1232. X        if (n == -1)
  1233. X            goto bad;
  1234. X        argv += (n-1); /* we're going to increment another up top */
  1235. X        }
  1236. X        when 'd':
  1237. X        if (!*++argv) {
  1238. X            print("specify a date for -%c\n", c);
  1239. X            goto bad;
  1240. X        }
  1241. X        if (!date1(*argv))
  1242. X            goto bad;
  1243. X        when 's' : case 'f': case 't': case 'h':
  1244. X        if (search_subj + search_from + search_to + *search_hdr > 1) {
  1245. X            print("specify one of `s', `f', `t' or `h' only\n");
  1246. X            goto bad;
  1247. X            }
  1248. X            if (c == 's')
  1249. X            search_subj = 1;
  1250. X        else if (c == 'f')
  1251. X            search_from = 1;
  1252. X        else if (c == 'h')
  1253. X            if (!*++argv)
  1254. X            print("Specify header to search for.\n");
  1255. X            else
  1256. X            (void) strcpy(search_hdr, *argv);
  1257. X        else
  1258. X            search_to = 1;
  1259. X        when 'x' : xflg = 1;
  1260. X        when 'i' : icase = 1;
  1261. X        otherwise:
  1262. X        print("pick: unknown flag: %c\n", argv[0][1]);
  1263. X        clear_msg_list(list);
  1264. X        return -1;
  1265. X    }
  1266. X    if (verbose) {
  1267. X    print_more("Searching for messages");
  1268. X    if (mdy[1] == 0)
  1269. X        print(" that %s \"%s\"", (xflg)? "doesn't contain": "contains",
  1270. X                (*argv)? *argv: "<previous expression>");
  1271. X    if (search_subj)
  1272. X        print_more(" in subject line");
  1273. X    else if (search_from)
  1274. X        print_more(" from author names");
  1275. X    else if (search_to)
  1276. X        print_more(" from the To: field");
  1277. X    else if (search_hdr[0])
  1278. X        print_more(" from the message header: \"%s:\"", search_hdr);
  1279. X    if (mdy[1] > 0) {
  1280. X        extern char *month_names[]; /* from dates.c */
  1281. X        print_more(" dated on or %s %s. %d, 19%d.",
  1282. X          (before)? "before": "after",
  1283. X          month_names[mdy[0]], mdy[1], mdy[2]);
  1284. X    }
  1285. X    print_more("\n");
  1286. X    }
  1287. X    if (mdy[1] > 0 && icase)
  1288. X    print("using date: -i flag ignored.\n");
  1289. X    ret = find_pattern(*argv, list);
  1290. bad:
  1291. X    before = o_before, search_from = o_search_from;
  1292. X    search_subj = o_search_subj, search_to = o_search_to, xflg = o_xflg;
  1293. X    for (c = 0; c < 3; c++)
  1294. X    mdy[c] = o_mdy[c];
  1295. X    return ret;
  1296. X}
  1297. X
  1298. find_pattern(p, list)
  1299. register char *p, list[];
  1300. X{
  1301. X    register int n, val, i; /* val is return value from regex or re_exec */
  1302. X    long bytes = 0;
  1303. X    char buf[BUFSIZ];
  1304. X    static char *err = (char *)-1;
  1305. X#ifdef REGCMP
  1306. X    char *regcmp(), *regex();
  1307. X#else /* REGCMP */
  1308. X    char *re_comp();
  1309. X#endif /* REGCMP */
  1310. X
  1311. X    if (p && *p == '\\')
  1312. X    p++;  /* take care of escaping special cases (`-', `\') */
  1313. X
  1314. X    /* specify what we're looking for */
  1315. X    if (p && *p) {
  1316. X    if (icase)
  1317. X        p = lcase_strcpy(buf, p);
  1318. X#ifdef REGCMP
  1319. X    if (err && p)
  1320. X        xfree(err);
  1321. X    if (p && !(err = regcmp(p, NULL))) {
  1322. X        print("regcmp error: %s\n", p);
  1323. X        clear_msg_list(list);
  1324. X        return -1;
  1325. X    }
  1326. X#else /* REGCMP */
  1327. X    if (err = re_comp(p)) {
  1328. X        print("re_comp error: %s\n", err);
  1329. X        clear_msg_list(list);
  1330. X        return -1;
  1331. X    }
  1332. X#endif /* REGCMP */
  1333. X    } else if (err == (char *)-1 && mdy[1] <= 0) {
  1334. X    print("No previous regular expression\n");
  1335. X    clear_msg_list(list);  /* doesn't matter really */
  1336. X    return -1;
  1337. X    }
  1338. X    /* start searching: set bytes, and message number: n */
  1339. X    for (n = 0; n < msg_cnt; n++)
  1340. X    if (msg_bit(list, n)) {
  1341. X        if (mdy[1] > 0) {
  1342. X        int msg_mdy[3];
  1343. X        if (!(p = msg_date(n))) {
  1344. X            unset_msg_bit(list, n);
  1345. X            continue; /* error: don't consider this message */
  1346. X        }       /* yr mo da */
  1347. X        (void) sscanf(p, "%2d%2d%2d",
  1348. X             &msg_mdy[2], &msg_mdy[0], &msg_mdy[1]);
  1349. X        msg_mdy[0]--;
  1350. X        Debug("checking %d's date: %d-%d-%d  ",
  1351. X                 n+1, msg_mdy[0]+1, msg_mdy[1], msg_mdy[2]);
  1352. X        /* start at year and wrap around.
  1353. X         * only when match the day (4), check for == (match)
  1354. X         */
  1355. X        for (i = 2; i < 5; i++)
  1356. X            if (before && msg_mdy[i%3] < mdy[i%3]
  1357. X            || !before && msg_mdy[i%3] > mdy[i%3]
  1358. X            || i == 4 && (msg_mdy[i%3] == mdy[i%3])) {
  1359. X                Debug("matched (%s).\n",
  1360. X                (i == 2)? "year" : (i == 3)? "month" : "day");
  1361. X                break;
  1362. X            } else if (msg_mdy[i%3] != mdy[i%3]) {
  1363. X            Debug("failed.\n");
  1364. X            unset_msg_bit(list, n);
  1365. X            break;
  1366. X            }
  1367. X        continue;
  1368. X        }
  1369. X        /* we must have the right date -- if we're searching for a
  1370. X         * string, find it.
  1371. X         */
  1372. X        (void) fseek(tmpf, msg[n].m_offset, L_SET);
  1373. X        bytes = 0;
  1374. X        while (bytes < msg[n].m_size) {
  1375. X        if (!search_subj && !search_from && !search_to &&
  1376. X            !*search_hdr && !(p = fgets(buf, BUFSIZ, tmpf)))
  1377. X            break;
  1378. X        else if (search_subj) {
  1379. X            if (!(p = header_field(n, "subject"))) {
  1380. X            unset_msg_bit(list, n);
  1381. X            break;
  1382. X            }
  1383. X        } else if (search_from) {
  1384. X            if (!(p = header_field(n, "from"))) {
  1385. X            register char *p2;
  1386. X            (void) fseek(tmpf, msg[n].m_offset, L_SET);
  1387. X            if (!(p2 = fgets(buf, BUFSIZ, tmpf)) ||
  1388. X                !(p = index(p2, ' ')))
  1389. X                continue;
  1390. X            p++;
  1391. X            if (p2 = any(p, " \t"))
  1392. X                *p2 = 0;
  1393. X            }
  1394. X        } else if (search_to) {
  1395. X            if (!(p = header_field(n, "to")) &&
  1396. X                !(p = header_field(n, "apparently-to"))) {
  1397. X            unset_msg_bit(list, n);
  1398. X            break;
  1399. X            }
  1400. X        }
  1401. X        else if (*search_hdr) {
  1402. X            if (!(p = header_field(n,  search_hdr))) {
  1403. X            unset_msg_bit(list, n);
  1404. X            break;
  1405. X            }
  1406. X        }
  1407. X        if (icase)
  1408. X            p = lcase_strcpy(buf, p);
  1409. X#ifdef REGCMP
  1410. X        val = !!regex(err, p, NULL); /* convert value to a boolean */
  1411. X#else /* REGCMP */
  1412. X        val = re_exec(p);
  1413. X#endif /* REGCMP */
  1414. X        if (val == -1) {   /* doesn't apply in system V */
  1415. X            print("Internal error for pattern search.\n");
  1416. X            clear_msg_list(list); /* it doesn't matter, really */
  1417. X            return -1;
  1418. X        }
  1419. X        if (xflg)
  1420. X            val = !val;
  1421. X        if (!val) {
  1422. X            /* unset the bit if match failed. If it matches later
  1423. X             * in the search, we'll reset to true in the next iteration.
  1424. X             * this doesn't apply for author or subject picks.
  1425. X             */
  1426. X            unset_msg_bit(list, n);
  1427. X            bytes += strlen(p);
  1428. X        } else {
  1429. X            set_msg_bit(list, n);
  1430. X            break;
  1431. X        }
  1432. X        if (search_subj || search_from || search_to || *search_hdr)
  1433. X            break;
  1434. X        }
  1435. X    }
  1436. X    return 0;
  1437. X}
  1438. X
  1439. X#ifdef CURSES
  1440. X/*
  1441. X * search for a pattern in composed message headers -- also see next function
  1442. X * flags ==  0   forward search (prompt).
  1443. X * flags == -1   continue search (no prompt).
  1444. X * flags ==  1   backward search (prompt).
  1445. X */
  1446. search(flags)
  1447. register int flags;
  1448. X{
  1449. X    register char   *p;
  1450. X    char           pattern[128];
  1451. X    register int    this_msg = current_msg, val = 0;
  1452. X    static char     *err = (char *)-1, direction;
  1453. X    int            (*oldint)(), (*oldquit)();
  1454. X#ifdef REGCMP
  1455. X    char *regcmp();
  1456. X#else /* REGCMP */
  1457. X    char *re_comp();
  1458. X#endif /* REGCMP */
  1459. X
  1460. X    if (msg_cnt <= 1) {
  1461. X    print("Not enough messages to invoke a search.\n");
  1462. X    return 0;
  1463. X    }
  1464. X    pattern[0] = '\0';
  1465. X    if (flags == -1)
  1466. X    print("continue %s search...", direction? "forward" : "backward");
  1467. X    else
  1468. X    print("%s search: ", flags? "backward" : "forward");
  1469. X    if (flags > -1)
  1470. X    if (Getstr(pattern, COLS-18, 0) < 0)
  1471. X        return 0;
  1472. X    else
  1473. X        direction = !flags;
  1474. X#ifdef REGCMP
  1475. X    if (err && *pattern)
  1476. X    xfree(err);
  1477. X    else if (err == (char *)-1 && !*pattern) {
  1478. X    print("No previous regular expression.");
  1479. X    return 0;
  1480. X    }
  1481. X    if (*pattern && !(err = regcmp(pattern, NULL))) {
  1482. X    print("Error in regcmp in %s", pattern);
  1483. X    return 0;
  1484. X    }
  1485. X#else /* REGCMP */
  1486. X    if (err = re_comp(pattern)) {
  1487. X    print(err);
  1488. X    return 0;
  1489. X    }
  1490. X#endif /* REGCMP */
  1491. X    move(LINES-1, 0), refresh();
  1492. X    on_intr();
  1493. X
  1494. X    do  {
  1495. X    if (direction)
  1496. X        current_msg = (current_msg+1) % msg_cnt;
  1497. X    else
  1498. X        if (--current_msg < 0)
  1499. X        current_msg = msg_cnt-1;
  1500. X        p = compose_hdr(current_msg);
  1501. X#ifdef REGCMP
  1502. X    val = !!regex(err, p, NULL); /* convert value to a boolean */
  1503. X#else /* REGCMP */
  1504. X    val = re_exec(p);
  1505. X#endif /* REGCMP */
  1506. X    if (val == -1)     /* doesn't apply in system V */
  1507. X        print("Internal error for pattern search.\n");
  1508. X    } while (!val && current_msg != this_msg && isoff(glob_flags, WAS_INTR));
  1509. X
  1510. X    if (ison(glob_flags, WAS_INTR)) {
  1511. X    print("Pattern search interruped.");
  1512. X    current_msg = this_msg;
  1513. X    } else if (val == 0)
  1514. X    print("Pattern not found.");
  1515. X
  1516. X    off_intr();
  1517. X    return val;
  1518. X}
  1519. X#endif /* CURSES */
  1520. X
  1521. X/*
  1522. X * parse a user given date string and set mdy[] array with correct
  1523. X * values.  Return 0 on failure.
  1524. X */
  1525. date1(p)
  1526. register char *p;
  1527. X{
  1528. X    register char *p2;
  1529. X    long      t;
  1530. X    int       i;
  1531. X    struct tm       *today;
  1532. X
  1533. X    if (*p == '-') {
  1534. X    before = 1;
  1535. X    skipspaces(1);
  1536. X    }
  1537. X    if (!isdigit(*p) && *p != '/') {
  1538. X    print("syntax error on date: \"%s\"\n", p);
  1539. X    return 0;
  1540. X    }
  1541. X    (void) time (&t);
  1542. X    today = localtime(&t);
  1543. X    for (i = 0; i < 3; i++)
  1544. X    if (!p || !*p || *p == '/') {
  1545. X        switch(i) {   /* default to today's date */
  1546. X        case 0: mdy[0] = today->tm_mon;
  1547. X        when 1: mdy[1] = today->tm_mday;
  1548. X        when 2: mdy[2] = today->tm_year;
  1549. X        }
  1550. X        if (p && *p)
  1551. X        p++;
  1552. X    } else {
  1553. X        p2 = (*p)? index(p+1, '/') : NULL;
  1554. X        mdy[i] = atoi(p); /* atoi will stop at the '/' */
  1555. X        if (i == 0 && (--(mdy[0]) < 0 || mdy[0] > 11)) {
  1556. X        print("Invalid month: %s\n", p);
  1557. X        return 0;
  1558. X        } else if (i == 1 && (mdy[1] < 1 || mdy[1] > 31)) {
  1559. X        print("Invalid day: %s\n", p);
  1560. X        return 0;
  1561. X        }
  1562. X        if (p = p2) /* set p to p2 and check to see if it's valid */
  1563. X        p++;
  1564. X    }
  1565. X    return 1;
  1566. X}
  1567. END_OF_FILE
  1568. if test 10751 -ne `wc -c <'pick.c'`; then
  1569.     echo shar: \"'pick.c'\" unpacked with wrong size!
  1570. fi
  1571. # end of 'pick.c'
  1572. fi
  1573. if test -f 'setopts.c' -a "${1}" != "-c" ; then 
  1574.   echo shar: Will not clobber existing file \"'setopts.c'\"
  1575. else
  1576. echo shar: Extracting \"'setopts.c'\" \(10923 characters\)
  1577. sed "s/^X//" >'setopts.c' <<'END_OF_FILE'
  1578. X/* setopts.c    (c) copyright 1986 (Dan Heller) */
  1579. X
  1580. X#include "mush.h"
  1581. X
  1582. X/* add an option indicated by "set option[=value]" or by "alias name alias" 
  1583. X * function is recursive, so multilists get appended accordingly
  1584. X */
  1585. add_option(list, argv)
  1586. register struct options **list;
  1587. register char **argv;
  1588. X{
  1589. X    register struct options *tmp;
  1590. X    struct options *calloc();
  1591. X    register char *option, *value = NULL;
  1592. X
  1593. X    if (!(option = *argv))
  1594. X    return 1;
  1595. X    /* check for one of three forms:
  1596. X     * option=value    option = value  option= value
  1597. X     * value can be in quotes to preserve whitespace
  1598. X     */
  1599. X    if (*++argv && !strcmp(*argv, "=")) {
  1600. X    if (value = *++argv) /* example: "set foo = " */
  1601. X        ++argv;
  1602. X    } else if (value = index(option, '=')) {
  1603. X    /* option=value  strip into option="option" value="value"; (quotes?) */
  1604. X    register char c, *p2;
  1605. X    *value = 0; /* option is now a null termined `option' */
  1606. X    if ((c = *++value) == '"' || c == '\'') {
  1607. X        *value++ = 0;
  1608. X        if (!(p2 = index(value, c))) {
  1609. X        print("No matching %c for %s.\n", c, option);
  1610. X        return 0;
  1611. X        } else
  1612. X        *p2 = 0;
  1613. X    } else if (!c) {  /* example: "set crt=" */
  1614. X        if (!*argv) {
  1615. X        print("No value for %s.\n", option);
  1616. X        return 0;
  1617. X        }
  1618. X        value = *argv++;
  1619. X    }
  1620. X    }
  1621. X    /* check to see if option is already set by attempting to unset it */
  1622. X    (void) un_set(list, option);
  1623. X
  1624. X    /* now make a new option struct and set fields */
  1625. X    if (!(tmp = calloc((unsigned)1, sizeof(struct options)))) {
  1626. X    error("calloc");
  1627. X    return -1;
  1628. X    }
  1629. X    tmp->option = savestr(option);
  1630. X    tmp->value = savestr(value); /* strdup handles the NULL case */
  1631. X
  1632. X    tmp->next = *list;
  1633. X    *list = tmp;
  1634. X
  1635. X    /* check for options which must have values or are used frequently */
  1636. X    if (*list == set_options) {
  1637. X#if defined(CURSES) || defined(SUNTOOL)
  1638. X    if (!strcmp(tmp->option, "no_reverse"))
  1639. X        turnoff(glob_flags, REV_VIDEO);
  1640. X    else
  1641. X#endif /* CURSES || SUNTOOL */
  1642. X    if (!strcmp(tmp->option, "prompt"))
  1643. X        prompt = (tmp->value)? tmp->value : DEF_PROMPT;
  1644. X    else if (!strcmp(tmp->option, "mil_time"))
  1645. X        turnon(glob_flags, MIL_TIME);
  1646. X    else if (!strcmp(tmp->option, "escape"))
  1647. X        escape = (tmp->value)? tmp->value : DEF_ESCAPE;
  1648. X    else if (!strcmp(tmp->option, "hdr_format"))
  1649. X        hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
  1650. X    else if (!strcmp(tmp->option, "crt")) {
  1651. X        if (!istool)
  1652. X        crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
  1653. X    } else if (!strcmp(tmp->option, "screen")) {
  1654. X        screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
  1655. X#ifdef CURSES
  1656. X        if (iscurses && screen > LINES-2)
  1657. X        screen = LINES-2;
  1658. X#endif /* CURSES */
  1659. X    } else if (!strcmp(tmp->option, "history"))
  1660. X        init_history((value && *value)? atoi(value) : 1);
  1661. X    }
  1662. X
  1663. X    if (*argv)
  1664. X    return add_option(list, argv);
  1665. X    return 1;
  1666. X}
  1667. X
  1668. X/*
  1669. X * If str is NULL, just print options and their values. Note that numerical
  1670. X * values are not converted to int upon return.  If str is not NULL
  1671. X * return the string that matched, else return NULL;
  1672. X */
  1673. char *
  1674. do_set(list, str)
  1675. register struct options *list;
  1676. register char *str;
  1677. X{
  1678. X    register struct options *opts;
  1679. X#ifdef SUNTOOL
  1680. X    int x,y;
  1681. X
  1682. X    if (istool && !str)
  1683. X    y = 10 + 2 * l_height(LARGE);
  1684. X#endif /* SUNTOOL */
  1685. X
  1686. X    if (!str && !istool)
  1687. X    (void) do_pager(NULL, TRUE); /* page using internal pager */
  1688. X
  1689. X    for (opts = list; opts; opts = opts->next)
  1690. X    if (!str) {
  1691. X#ifdef SUNTOOL
  1692. X        if (istool)
  1693. X        pw_text(msg_win, 5, y, PIX_SRC, fonts[DEFAULT], opts->option);
  1694. X        else
  1695. X#endif /* SUNTOOL */
  1696. X        (void) do_pager(opts->option, FALSE);
  1697. X        if (opts->value)
  1698. X#ifdef SUNTOOL
  1699. X        if (istool) {
  1700. X            x = 30*l_width(DEFAULT);
  1701. X            pw_text(msg_win, x,y, PIX_SRC, fonts[DEFAULT], opts->value);
  1702. X            pw_text(msg_win, x+1, y, PIX_SRC|PIX_DST,
  1703. X                 fonts[DEFAULT], opts->value);
  1704. X            x += strlen(opts->value)*l_width(DEFAULT);
  1705. X        } else
  1706. X#endif /* SUNTOOL */
  1707. X        {
  1708. X            (void) do_pager("     \t", FALSE);
  1709. X            (void) do_pager(opts->value, FALSE);
  1710. X        }
  1711. X#ifdef SUNTOOL
  1712. X        if (istool)
  1713. X        Clrtoeol(msg_win, x, y, DEFAULT), y += l_height(DEFAULT);
  1714. X        else
  1715. X#endif /* SUNTOOL */
  1716. X        if (do_pager("\n", FALSE) == EOF)
  1717. X            break;
  1718. X    } else {
  1719. X        if (strcmp(str, opts->option))
  1720. X        continue;
  1721. X        if (opts->value)
  1722. X        return opts->value;
  1723. X        else
  1724. X        return "";
  1725. X    }
  1726. X
  1727. X    if (!str && !istool)
  1728. X    (void) do_pager(NULL, FALSE); /* terminate internal pager */
  1729. X
  1730. X    /* if we still haven't matched, check for environment vars */
  1731. X    if (str && list == set_options) {
  1732. X    register int N, n;
  1733. X    for (N = 0; environ[N]; N++) {
  1734. X        char *p = index(environ[N], '=');
  1735. X        if (p)
  1736. X        *p = 0;
  1737. X        n = lcase_strcmp(str, environ[N]);
  1738. X        if (p)
  1739. X        *p = '=';
  1740. X        if (!n)
  1741. X        return p+1;
  1742. X    }
  1743. X    }
  1744. X    return NULL;
  1745. X}
  1746. X
  1747. X/*
  1748. X * unset the variable described by p in the list "list".
  1749. X * if the variable isn't set, then return 0, else return 1.
  1750. X */
  1751. un_set(list, p)
  1752. register struct options **list;
  1753. register char *p;
  1754. X{
  1755. X    register struct options *opts = *list, *tmp;
  1756. X
  1757. X    if (!list || !*list || !p || !*p)
  1758. X    return 0;
  1759. X    if (*list == set_options) {
  1760. X#if defined(CURSES) || defined(SUNTOOL)
  1761. X    if (!strcmp(p, "no_reverse"))
  1762. X        turnon(glob_flags, REV_VIDEO);
  1763. X    else
  1764. X#endif /* CURSES || SUNTOOL */
  1765. X    if (!strcmp(p, "prompt"))
  1766. X        prompt = DEF_PROMPT;
  1767. X    else if (!strcmp(p, "mil_time"))
  1768. X        turnoff(glob_flags, MIL_TIME);
  1769. X    else if (!strcmp(p, "escape"))
  1770. X        escape = DEF_ESCAPE;
  1771. X    else if (!strcmp(p, "hdr_format"))
  1772. X        hdr_format = DEF_HDR_FMT;
  1773. X    else if (!strcmp(p, "crt"))
  1774. X        crt = 18;
  1775. X    else if (!strcmp(p, "screen")) {
  1776. X        screen = 18;
  1777. X#ifdef CURSES
  1778. X        if (iscurses && screen > LINES-2)
  1779. X        screen = LINES-2;
  1780. X#endif /* CURSES */
  1781. X    } else if (!strcmp(p, "history"))
  1782. X        init_history(1);
  1783. X    }
  1784. X
  1785. X    if (!strcmp(p, opts->option)) {
  1786. X    *list = (*list)->next;
  1787. X    xfree (opts->option);
  1788. X    if (opts->value)
  1789. X        xfree(opts->value);
  1790. X    xfree((char *)opts);
  1791. X    return 1;
  1792. X    }
  1793. X    for ( ; opts->next; opts = opts->next)
  1794. X    if (!strcmp(p, opts->next->option)) {
  1795. X        tmp = opts->next;
  1796. X        opts->next = opts->next->next;
  1797. X        xfree (tmp->option);
  1798. X        if (tmp->value)
  1799. X        xfree(tmp->value);
  1800. X        xfree ((char *)tmp);
  1801. X        return 1;
  1802. X    }
  1803. X    return 0;
  1804. X}
  1805. X
  1806. X/* The functions below return -1 since they don't affect
  1807. X * messages. This prevents piping from do_loop().
  1808. X */
  1809. set(n, argv)
  1810. register int n;
  1811. register char **argv;
  1812. X{
  1813. X    char firstchar = **argv;
  1814. X    register char *cmd = *argv;
  1815. X    register struct options **list;
  1816. X
  1817. X    if (*cmd == 'u')
  1818. X    cmd += 2;
  1819. X    if (*++argv && !strcmp(*argv, "-?"))
  1820. X    return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
  1821. X    if (*argv && **argv == '?') {
  1822. X    char buf[BUFSIZ];
  1823. X    int incurses;
  1824. X    if (!strcmp(*argv, "?all")) {
  1825. X        if (incurses = iscurses) /* assign and compare to TRUE */
  1826. X        clr_bot_line(), iscurses = FALSE;
  1827. X        (void) do_pager(NULL, TRUE); /* start internal pager */
  1828. X        for (n = 0; variable_stuff(n, NULL, buf); n++)
  1829. X        if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
  1830. X            break;
  1831. X        (void) do_pager(NULL, FALSE); /* terminate pager */
  1832. X        iscurses = incurses;
  1833. X    } else {
  1834. X        /* May return null if variable not set. */
  1835. X        (void) variable_stuff(0, (*argv)+1, buf);
  1836. X        print("%s\n", buf);
  1837. X    }
  1838. X    return -1;
  1839. X    }
  1840. X
  1841. X    if (firstchar == 'u') {
  1842. X    if (!*argv)
  1843. X        print("%s what?\n", cmd);
  1844. X    else {
  1845. X        list = (*cmd == 'i')? &ignore_hdr : &set_options;
  1846. X        do  if (!strcmp(*argv, "*"))
  1847. X            while (*list)
  1848. X            (void) un_set(list, (*list)->option);
  1849. X        else if (!un_set(list, *argv))
  1850. X            print("un%s: %s not set\n",
  1851. X            (*cmd == 'i')? "ignore" : "set", *argv);
  1852. X        while (*++argv);
  1853. X    }
  1854. X    return -1;
  1855. X    }
  1856. X    if (!*argv)
  1857. X    (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
  1858. X    else
  1859. X    (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
  1860. X    return -1;
  1861. X}
  1862. X
  1863. alts(argc, argv)
  1864. register char **argv;
  1865. X{
  1866. X    char buf[256], buf2[256], *p;
  1867. X    u_long save_bang = ison(glob_flags, IGN_BANG);
  1868. X
  1869. X    if (argc && *++argv && !strcmp(*argv, "-?"))
  1870. X    return help(0, "alts_help", cmd_help);
  1871. X    if (argc > 1) {
  1872. X    (void) argv_to_string(buf2, argv);
  1873. X    (void) sprintf(buf, "set alternates=\"%s\"",  buf2);
  1874. X    turnon(glob_flags, IGN_BANG);
  1875. X    if (argv = make_command(buf, TRPL_NULL, &argc))
  1876. X        (void) do_command(argc, argv, msg_list);
  1877. X    if (!save_bang)
  1878. X        turnoff(glob_flags, IGN_BANG);
  1879. X    } else
  1880. X    if (!(p = do_set(set_options, "alternates")))
  1881. X        print("No alternate hostnames set.\n");
  1882. X    else
  1883. X        print("Alternate hostnames: %s\n", p);
  1884. X    return -1;
  1885. X}
  1886. X
  1887. save_opts(cnt, argv)
  1888. char **argv;
  1889. X{
  1890. X    char file[256], *tmp;
  1891. X    register FILE *fp;
  1892. X
  1893. X    if (cnt && *++argv && !strcmp(*argv, "-?"))
  1894. X    return help(0, "source_help", cmd_help);
  1895. X    if (cnt && *argv)
  1896. X    (void) strcpy(file, *argv);
  1897. X    else if (tmp = getenv("MAILRC"))
  1898. X    (void) strcpy(file, tmp);
  1899. X    else {
  1900. X    char *home = do_set(set_options, "home");
  1901. X    if (!home || !*home)
  1902. X        home = ALTERNATE_HOME;
  1903. X    /* if .musrc doesn't exist, check .mailrc. If neither, force .mushrc */
  1904. X    if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
  1905. X            Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
  1906. X        (void) sprintf(file, "%s/%s", home, MAILRC);
  1907. X    }
  1908. X
  1909. X    cnt = 1;
  1910. X    tmp = getpath(file, &cnt);
  1911. X    if (cnt) {
  1912. X    if (cnt == -1)
  1913. X        print("%s: %s\n", file, tmp);
  1914. X    else
  1915. X        print("%s is a directory.\n", tmp);
  1916. X    return -1;
  1917. X    }
  1918. X    /* See if the file exists and confirm overwrite */
  1919. X    if (!Access(tmp, F_OK)) {
  1920. X    int overwrite = TRUE;
  1921. X    char buf[4];
  1922. X    print("\"%s\" exists. Overwrite? ", tmp);
  1923. X    if (!istool) {
  1924. X        if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
  1925. X        overwrite = FALSE;
  1926. X    }
  1927. X#ifdef SUNTOOL
  1928. X    else {
  1929. X        int c = confirm(panel_sw->ts_windowfd);
  1930. X        if (lower(c) != 'y' && c != MS_LEFT)
  1931. X        overwrite = FALSE;
  1932. X    }
  1933. X#endif /* SUNTOOL */
  1934. X    if (!overwrite) {
  1935. X        print("\"%s\" unchanged.\n", tmp);
  1936. X        return -1;
  1937. X    }
  1938. X    }
  1939. X    if (!(fp = fopen(tmp, "w"))) {
  1940. X    error("Can't open %s", file);
  1941. X    return -1;
  1942. X    }
  1943. X
  1944. X    save_list("basic variable settings", set_options, "set", '=', fp);
  1945. X
  1946. X    save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
  1947. X
  1948. X    save_list("aliases", aliases, "alias", 0, fp);
  1949. X
  1950. X    save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
  1951. X
  1952. X    save_list("command abbreviations", functions, "cmd", ' ', fp);
  1953. X
  1954. X    save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
  1955. X
  1956. X    fclose(fp);
  1957. X    print("All variables and options saved in %s\n", tmp);
  1958. X    return -1;
  1959. X}
  1960. X
  1961. save_list(title, list, command, equals, fp)
  1962. struct options *list;
  1963. register char *command, *title, equals;
  1964. register FILE *fp;
  1965. X{
  1966. X    register struct options *opts;
  1967. X    register char *p;
  1968. X
  1969. X    if (!list)
  1970. X    return;
  1971. X    fprintf(fp, "#\n# %s\n#\n", title);
  1972. X    for (opts = list; opts; opts = opts->next) {
  1973. X    fprintf(fp, "%s %s", command, opts->option);
  1974. X    if (opts->value && *opts->value) {
  1975. X        register char *quote;
  1976. X        if (!equals)
  1977. X        quote = NO_STRING;
  1978. X        else if (p = any(opts->value, "\"'"))
  1979. X        if (*p == '\'') quote = "\"";
  1980. X        else quote = "'";
  1981. X        else
  1982. X        if (!any(opts->value, " \t;|"))
  1983. X            quote = NO_STRING;
  1984. X        else quote = "'";
  1985. X        fputc(equals? equals: ' ', fp);
  1986. X        fprintf(fp, "%s%s%s", quote, opts->value, quote);
  1987. X    }
  1988. X    fputc('\n', fp);
  1989. X    }
  1990. X}
  1991. END_OF_FILE
  1992. if test 10923 -ne `wc -c <'setopts.c'`; then
  1993.     echo shar: \"'setopts.c'\" unpacked with wrong size!
  1994. fi
  1995. # end of 'setopts.c'
  1996. fi
  1997. echo shar: End of archive 4 \(of 14\).
  1998. cp /dev/null ark4isdone
  1999. MISSING=""
  2000. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2001.     if test ! -f ark${I}isdone ; then
  2002.     MISSING="${MISSING} ${I}"
  2003.     fi
  2004. done
  2005. if test "${MISSING}" = "" ; then
  2006.     echo You have unpacked all 14 archives.
  2007.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2008. else
  2009.     echo You still need to unpack the following archives:
  2010.     echo "        " ${MISSING}
  2011. fi
  2012. ##  End of shell archive.
  2013. exit 0
  2014.